//
//  AccountController.swift
//  App
//
//  Created by 汤泽川 on 2019/3/25.
//

import Vapor
import FluentMySQL

class AccountController : RouteCollection {
    func boot(router: Router) throws {
        router.post(RequestModel<EmailContent>.self, at: "get_verify_code", use: getVerifyCodeHandle);
        router.post(RequestModel<UserRegisterInfo>.self, at: "register", use: register)
        router.post(RequestModel<UserLoginRequest>.self, at: "login", use: login)
        router.post(RequestModel<UserRegisterInfo>.self, at: "reset_password", use: resetPassword)
        router.post(RequestModel<CheckUserFollowStatusRequest>.self, at: "follow_status", use: quaryFollowStatus)
        
        let userAuthRouter = router.grouped(UserAuthMiddleware())
        
        userAuthRouter.post(RequestModel<UserInfo>.self, at: "quary", use: quaryUserInfo)
        userAuthRouter.post(RequestModel<EmptyData>.self, at: "logout", use: logout)
        userAuthRouter.post(RequestModel<EmptyData>.self, at: "quary_user_data", use: quaryUserData)
        userAuthRouter.post(RequestModel<UserFollowRequest>.self, at: "follow", use: changeFollowStatus)
        userAuthRouter.post(RequestModel<QuaryFollowListRequest>.self, at: "followlist", use: quaryFollowerList)
        userAuthRouter.post(RequestModel<ChangeuserProfileRequest>.self, at: "change_profile", use: changeUserProfile)
    }
}

extension AccountController {
    /// 获取验证码
    func getVerifyCodeHandle(_ req : Request, content : RequestModel<EmailContent>) throws -> Future<Response> {
        
        return VerifyCode.query(on: req).filter(\.email == content.data.email).all().flatMap({ verifyCodes in
            // delete exist verify code
            for element in verifyCodes {
                _ = element.delete(on: req)
            }
            
            var verifyCode = VerifyCode(email: content.data.email)
            verifyCode.createVerifyCode()
            
            return verifyCode.save(on: req).flatMap({ code in
                do {
                    return try code.sendVerifyByEmail(req: req).flatMap({ result in
                        if result {
                            return try ResponseModel<String>(0, "发送成功").encode(for: req)
                        } else {
                            return code.delete(on: req).map({ _ in
                                throw APIError.sendEmailError
                            })
                        }
                    })
                }
                catch {
                    return code.delete(on: req).map({ _ in
                        throw error
                    })
                }
            })
        })
    }
    
    /// 用户注册
    public func register(_ req : Request, _ content : RequestModel<UserRegisterInfo>) throws -> Future<Response> {
        var userRegisterInfo = content.data
        return try userRegisterInfo.checkRegisterEnable(req: req).flatMap({
            _ in
            userRegisterInfo.password = userRegisterInfo.password.sha256
            _ = userRegisterInfo.save(on: req)
            _ = UserInfo(username: userRegisterInfo.username, email: userRegisterInfo.email).save(on: req)
            return try ResponseModel<Int>(0, "注册成功").encode(for: req)
        }).catchFlatMap({ error in
            throw error
        })
    }
    /// 用户登录
    public func login(_ req : Request, _ content : RequestModel<UserLoginRequest>) throws -> Future<Response> {
        let loginInfo = content.data
        return UserRegisterInfo.query(on: req).filter(\.username == loginInfo.username).filter(\.password == loginInfo.password.sha256).first().flatMap({
            registerInfo in
            if registerInfo == nil {
                throw APIError.validateLoginError
            }
            return UserInfo.query(on: req).filter(\.username == loginInfo.username).first().flatMap({
                userInfo in
                guard let userInfo = userInfo else {
                    throw APIError.userDoesNotExistError
                }
                let accessToken = UserAccessToken.createTokenWithUsername(username: loginInfo.username)
                _ = accessToken.save(on: req)
                let userLoginResponse = UserLoginResponse(accessToken: accessToken.accessToken, userInfo: userInfo)
                let responseModel = ResponseModel<UserLoginResponse>.successResponse(userLoginResponse)
                return try responseModel.encode(for: req)
            }).catchFlatMap({
                error in
                throw error
            })
        })
    }
    
    public func logout(_ req : Request, _ content : RequestModel<EmptyData>) throws -> Future<Response> {
        return UserAccessToken.query(on: req).filter(\UserAccessToken.accessToken == content.accessToken!).first().flatMap {
            token in
            _ = token?.delete(on: req)
            return try ResponseModel<String>.successResponse().encode(for: req)
        }
    }
    
    /// 查询用户信息，需登录
    public func quaryUserInfo(_ req : Request, _ content : RequestModel<UserInfo>) throws -> Future<Response> {
        let userInfo = content.data
        return UserInfo.query(on: req).filter(\.username == userInfo.username).first().flatMap({
            userInfo in
            guard let userInfo = userInfo else {
                throw APIError.userDoesNotExistError
            }
            let response = ResponseModel<UserInfo>.successResponse(userInfo)
            return try response.encode(for: req)
        })
    }
    
    /// 查询用户数据
    public func quaryUserData(_ req : Request, _ content : RequestModel<EmptyData>) throws -> Future<Response> {
        return try UserAccessToken.queryUserInfo(accessToken: content.accessToken!, req: req).flatMap {
            userInfo in
            return CollectionStoryInfo.query(on: req).filter(\CollectionStoryInfo.userId == userInfo.id!).count().flatMap {
                collectCount in
                return UserFollowInfo.query(on: req).filter(\.userId == userInfo.id!).count().flatMap {
                    followingCount in
                    return UserFollowInfo.query(on: req).filter(\.targetId == userInfo.id!).count().flatMap {
                        followerCount in
                        return try ResponseModel<UserDataResponse>.successResponse(UserDataResponse(follwoing: followingCount, follower: followerCount, collectCount: collectCount)).encode(for: req)
                    }
                }
            }
        }
    }
    
    /// 重置密码
    public func resetPassword(_ req : Request, _ content : RequestModel<UserRegisterInfo>) throws -> Future<Response> {
        let newRegisterInfo = content.data
        if newRegisterInfo.validatePassword() == false {
            throw APIError.illegalPasswordError
        }
        guard let verifyCode = newRegisterInfo.verifyCode else {
            throw APIError.emptyVerifyCodeError
        }
        return UserRegisterInfo.query(on: req).filter(\.username == newRegisterInfo.username).filter(\.email == newRegisterInfo.email).first().flatMap({
            oldRegisterInfo in
            guard var oldRegisterInfo = oldRegisterInfo else {
                throw APIError.resetPasswordError
            }
            return VerifyCode.query(on: req).filter(\.email == newRegisterInfo.email).filter(\.code == verifyCode).first().flatMap({
                storedCode in
                if storedCode == nil {
                    throw APIError.illegalVerifyCodeError
                }
                _ = storedCode?.delete(on: req)
                oldRegisterInfo.password = newRegisterInfo.password.sha256
                _ = oldRegisterInfo.update(on: req)
                return try ResponseModel<String>.successResponse().encode(for: req)
            })
        })
    }
    
    /// 改变关注状态
    public func changeFollowStatus(_ req : Request, _ content : RequestModel<UserFollowRequest>) throws -> Future<Response> {
        return try UserAccessToken.queryUserInfo(accessToken: content.accessToken!, req: req).flatMap {
            userInfo in
            return UserFollowInfo.query(on: req).filter(\UserFollowInfo.userId == userInfo.id!).filter(\UserFollowInfo.targetId == content.data.targetId).first().flatMap {
                followInfo in
                if content.data.status == 0 {
                    _ = followInfo?.delete(on: req)
                } else {
                    if followInfo == nil {
                        _ = UserFollowInfo(id: nil, createdAt: nil, updatedAt: nil, userId: userInfo.id!, targetId: content.data.targetId).save(on: req)
                    }
                }
                return try ResponseModel<String>.successResponse().encode(for: req)
            }
        }
    }
    /// 查询关注人列表
    public func quaryFollowerList(_ req : Request, _ content : RequestModel<QuaryFollowListRequest>) throws -> Future<Response> {
        return try UserAccessToken.queryUserInfo(accessToken: content.accessToken!, req: req).flatMap {
            userInfo in
            return UserFollowInfo.query(on: req).join(\UserInfo.id, to: \UserFollowInfo.targetId).filter(\UserFollowInfo.userId == userInfo.id!).range(lower: content.data.page * content.data.count, upper:(content.data.page + 1 ) * content.data.count - 1).alsoDecode(UserInfo.self).all().flatMap {
                result in
                return try ResponseModel<[UserInfo]>.successResponse(result.map {
                    return $0.1
                }).encode(for: req)
            }
        }
    }
    /// 查询关注状态
    public func quaryFollowStatus(_ req : Request, _ content : RequestModel<CheckUserFollowStatusRequest>) throws -> Future<Response> {
        if content.accessToken == nil {
            return try ResponseModel<CheckUserFollowStatusResponse>.successResponse(CheckUserFollowStatusResponse(status: 0)).encode(for: req)
        } else {
            return try UserAccessToken.queryUserInfo(accessToken: content.accessToken!, req: req).flatMap {
                userInfo in
                return UserFollowInfo.query(on: req).filter(\UserFollowInfo.userId == userInfo.id!).filter(\UserFollowInfo.targetId == content.data.targetId).count().flatMap {
                    count in
                    return try ResponseModel<CheckUserFollowStatusResponse>.successResponse(CheckUserFollowStatusResponse(status: count > 0 ? 1 : 0)).encode(for: req)
                }
            }
        }
    }
    /// 修改个人信息
    public func changeUserProfile(_ req : Request, _ content : RequestModel<ChangeuserProfileRequest>) throws -> Future<Response> {
        return try UserAccessToken.queryUserInfo(accessToken: content.accessToken!, req: req).flatMap {
            userInfo in
            var userInfo = userInfo
            if content.data.avatarUrl != nil {
                userInfo.avatarUrl = content.data.avatarUrl
            }
            if content.data.introduce != nil {
                userInfo.introduce = content.data.introduce
            }
            return userInfo.save(on: req).flatMap {
                newInfo in
                return try ResponseModel<UserInfo>.successResponse(newInfo).encode(for: req)
            }
            
        }
    }
}
